package com.flute.icrawler.htmlparser.util;

import java.util.ArrayList;
import java.util.List;
import javax.xml.xpath.*;
import org.w3c.dom.*;

public class DOMUtil {

	public DOMUtil() {
	}

	public static String getHtml(Node node) {
		StringBuffer buffer = new StringBuffer();
		getHtml(node, buffer, null, null);
		return buffer.toString();
	}

	public static String getHtml(Node node, List filterTags, List filterAttrs) {
		StringBuffer buffer = new StringBuffer();
		getHtml(node, buffer, filterTags, filterAttrs);
		return buffer.toString();
	}

	public static String getNodeValue(Node node, List filterTags) {
		StringBuffer buffer = new StringBuffer();
		getNodeValue(node, buffer, filterTags);
		return buffer.toString();
	}

	public static String getNodeValue(Node node) {
		StringBuffer buffer = new StringBuffer();
		getNodeValue(node, buffer, null);
		return buffer.toString();
	}

	public static List getLinks(Document doc) {
		List list = new ArrayList();
		try {
			String xpath = "//A/@href|//iframe/@src|//frame/@src";
			NodeList nodes = xpath(doc, xpath);
			for (int i = 0; i < nodes.getLength(); i++) {
				Node node = nodes.item(i);
				String link = node.getNodeValue();
				if (link != null && !link.trim().equals("")
						&& !link.trim().equals("#"))
					list.add(link.trim());
			}

		} catch (Exception exception) {
		}
		return list;
	}

	public static List getImgs(Document doc) {
		List list = new ArrayList();
		try {
			String xpath = "//IMG/@src";
			NodeList nodes = xpath(doc, xpath);
			for (int i = 0; i < nodes.getLength(); i++) {
				Node node = nodes.item(i);
				String link = node.getNodeValue();
				if (link != null && !link.trim().equals(""))
					list.add(link.trim());
			}

		} catch (Exception exception) {
		}
		return list;
	}

	public static List getNodeHtml(Document doc, String xpath) {
		List list = new ArrayList();
		try {
			NodeList nodes = xpath(doc, xpath);
			for (int i = 0; i < nodes.getLength(); i++) {
				Node node = nodes.item(i);
				String html = getHtml(node);
				if (html != null && !html.trim().equals(""))
					list.add(html.trim());
			}

		} catch (Exception exception) {
		}
		return list;
	}

	private static void getHtml(Node node, StringBuffer buffer,
			List filterTags, List filterAttrs) {
		if (node.getNodeType() == 3) {
			String text = node.getNodeValue();
			if (text != null && !text.trim().equals(""))
				buffer.append(text.trim());
		} else if (node.getNodeType() == 1) {
			String tag = node.getNodeName().toUpperCase();
			if (filterTags != null && filterTags.contains(tag))
				return;
			buffer.append("<").append(tag);
			NamedNodeMap attrs = node.getAttributes();
			for (int i = 0; i < attrs.getLength(); i++) {
				Node attr = attrs.item(i);
				String attrName = attr.getNodeName().toLowerCase();
				if (filterAttrs == null || !filterAttrs.contains(attrName))
					buffer.append(" ").append(attrName).append("='")
							.append(attr.getNodeValue()).append("'");
			}

			buffer.append(">");
			if (node.hasChildNodes()) {
				NodeList nodes = node.getChildNodes();
				for (int i = 0; i < nodes.getLength(); i++)
					getHtml(nodes.item(i), buffer, filterTags, filterAttrs);

			}
			buffer.append("</").append(tag).append(">");
		} else if (node.getNodeType() == 9)
			getHtml(((Node) (((Document) node).getDocumentElement())), buffer,
					filterTags, filterAttrs);
		else if (node.getNodeType() == 2)
			buffer.append(node.getNodeValue());
	}

	private static void getNodeValue(Node node, StringBuffer buffer,
			List filterTags) {
		if (node.getNodeType() == 3) {
			String value = node.getNodeValue();
			if (value != null && !value.trim().equals(""))
				buffer.append(node.getNodeValue().trim());
		} else if (node.getNodeType() == 1) {
			Element element = (Element) node;
			String tag = element.getTagName().toUpperCase();
			if (filterTags != null && filterTags.contains(tag))
				return;
			if (node.hasChildNodes()) {
				NodeList nodes = node.getChildNodes();
				for (int i = 0; i < nodes.getLength(); i++) {
					Node child = nodes.item(i);
					getNodeValue(child, buffer, filterTags);
				}

			}
		} else if (node.getNodeType() == 2) {
			String text = node.getNodeValue();
			if (text != null)
				buffer.append(text);
		} else if (node.getNodeType() == 9)
			getNodeValue(((Node) (((Document) node).getDocumentElement())),
					buffer, filterTags);
		else
			return;
	}

	public static NodeList xpath(Document doc, String xpath)
			throws XPathExpressionException {
		return (NodeList) XPATH.evaluate(xpath, doc, XPathConstants.NODESET);
	}

	private static final XPath XPATH = XPathFactory.newInstance().newXPath();

}
